package com.zte.claa.inficombo.csa.app.service.csa.impl;


import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.zte.claa.inficombo.csa.app.dao.mysql.impl.AlarmCodeMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.DevBaseMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.DevTypeMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.FFResDevMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.ProjectMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.ResIndexDataModelMapper;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.ResShadowMapper;
import com.zte.claa.inficombo.csa.app.model.dev.DevBase;
import com.zte.claa.inficombo.csa.app.model.dev.DevPagePara;
import com.zte.claa.inficombo.csa.app.model.dev.DevTpExtData;
import com.zte.claa.inficombo.csa.app.model.dev.DevTypeBase;
import com.zte.claa.inficombo.csa.app.model.dev.DevTypeModel;
import com.zte.claa.inficombo.csa.app.model.dev.ResIndexDataModel;
import com.zte.claa.inficombo.csa.app.model.dev.ResourceShadow;
import com.zte.claa.inficombo.csa.app.model.dev.SensorDevEuiPV;
import com.zte.claa.inficombo.csa.app.model.proj.ProjectDBPara;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmCode;
import com.zte.claa.inficombo.csa.app.model.redis.DevMeteData;
import com.zte.claa.inficombo.csa.app.service.sapi.ffhost.bean.FFResDevBase;
import com.zte.claa.inficombo.csa.app.util.SecurityUtil;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.DiskStoreConfiguration;
import net.sf.ehcache.config.PersistenceConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

/**
 * @author lee
 *
 */

@Service("BaseCacheManager")
@Lazy(false)
public class BaseCacheManager implements InitializingBean, DisposableBean {	
	// 缓存名称
	// 1. Dev对象缓存，key：deveui, value: DevBase;
	private static final String DEV_MAP_CACHE = "deveui2DevCache";
	// 2. DevTypemodel对象缓存，key: devtypeid, value: DevTypeModel;
	private static final String DEVTP_MODEL_CACHE = "devtp2ModelCache";
	// 3. ProjectDbInfo对象缓存，key：projectId, value: ProjectDBPara;
	private static final String PROJ_DBPARA_CACHE = "proj2DBParaCache";
	// 4. DevTpExtData对象缓存，key：devtpid, value: DevTpExtData;
	private static final String DEVTP_EXT_CACHE = "devtp2ExtCache";
	// 5. Sensor2Deveui对象缓存，key：sensorid, value: SensorDevEuiPV;
	private static final String SENSOR_DEV_MAP_CACHE = "sensor2DevCache";
	// 6. 需要二次加工的metedata数据缓存（如北秦设备，上报数据分包不规范，在CSA侧尝试做简单的合并）, key: deveui, value: DevMeteData
	private static final String COMBINE_DATA_CACHE = "combineDataCache";	
	// 7. 消防传输装置/主机/部件的缓存, key: deveui, value: FFResDevBase
	private static final String FF_DEV_CACHE = "ffdevDataCache";
	// 8. 消防传输装置/主机/部件的缓存, key: addrkey(FFResDevBase.buildAddrCacheKey), value: FFResDevBase
	private static final String FF_ADDR_CACHE = "ffaddrDataCache";
	// 9. 消防传输装置/主机/部件的最新数据缓存, key: deveui, value: 各类data的json字符串.
	private static final String FF_NEWDATA_CACHE = "ffnewDataCache";
    private static final String PHOTO_DATA_CACHE = "photoDataCache";
	// 10. ResourceShadow对象缓存，key: resid, value: ResourceShadow;
	private static final String RES_MAP_CACHE = "resid2ShadowCache";
	// 11. 逻辑资源最新指标数据缓存（避免重复上报无变化数据）, key: resid, value: DevMeteData
	private static final String RES_INDEX_DATA_CACHE = "resIndexDataCache";
	// 12. 低电量报警标志缓存,避免重复发送报警与恢复报警消息, key: deveui, value: Integer
	private static final String LOW_POWER_ALARM_FLAG_CACHE = "lowPowerAlarmFlagCache";
	
	// 日志记录
	private final Logger logger = LoggerFactory.getLogger(BaseCacheManager.class);
	
	@Autowired
	private DevBaseMapper devMapper;
	
	@Autowired
	private ProjectMapper projMapper;
	
	@Autowired
	private DevTypeMapper devtpMapper;
	
	@Autowired
	private FFResDevMapper ffResMapper;
	
	@Autowired
	private ResIndexDataModelMapper resIndexModelMapper;
	
	@Autowired
	private ResShadowMapper resShadowMapper;
	
	@Autowired
	private AlarmCodeMapper alarmCodeMapper;
	
	// 缓存管理器及缓存对象
    private CacheManager manager = null;  
    // 1. key：deveui, value: DevBase; (批量加载，懒加载模式数据库IO次数太多)
    private Cache devCache = null;
    // 2. devtypeid, value: DevTypeModel; (注：懒加载模式)
    private Cache devtpModelCache = null;
    // 3. key：projectId, value: ProjectDBPara; 
    private Cache projDBParaCache = null;
    // 4. DevTpExtData对象缓存，key：devtpid, value: DevTpExtData;
    private Cache devtpExtCache = null;
    // 5. Sensor2Deveui对象缓存，key：sensorid, value: SensorDevEuiPV;
    private Cache sensorPVCache = null;
    // 6. combineDataCache，key: deveui, value: DevMeteData
    private Cache combineDataCache = null;
    // 7. 消防传输装置/主机/部件的缓存, key: deveui, value: FFResDevBase
 	private Cache ffdevDataCache = null;
 	// 8. 消防传输装置/主机/部件的缓存, key: addrkey(FFResDevBase.buildAddrCacheKey), value: FFResDevBase
 	private Cache ffaddrDataCache = null;
 	// 9. 消防传输装置/主机/部件的最新数据缓存, key: deveui, value: 各类data的json字符串.
 	private Cache ffnewDataCache = null;
    private Cache photoDataCache = null;
 	// 10. ResourceShadow对象缓存，key: resid, value: ResourceShadow; 懒加载模式，节省资源!!
	private Cache resShadowCache = null;
	// 11. 逻辑资源最新指标数据缓存（避免重复上报无变化数据）, key: resid, value: DevMeteData
	private Cache resNewIndexDataCache = null;
	//12. 低电量报警标志缓存
	private Cache lowPowerAlarmFlagCache = null;
	
	// 告警码缓存，直接放内存，懒加载模式: key: devtype.alarmcode, value: AlarmCode
	private Map<String, AlarmCode> alarmCodeMap = new ConcurrentHashMap<String, AlarmCode>();
	

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and ApplicationContextAware).
     * <p>This method allows the bean instance to perform initialization only
     * possible when all bean properties have been set and to throw an
     * exception in the event of misconfiguration.
     * @throws Exception in the event of misconfiguration (such
     * as failure to set an essential property) or if initialization fails.
     */
	@Override
	public void afterPropertiesSet() throws Exception {
		logger.info("Begin init BaseCacheManager...");
		this.init();		
	}   

	@Override
	public void destroy() throws Exception {
		this.shutdown();
		logger.warn("BaseCacheManager is shutdown!");
	}
    
    /**
     * 构建器.
     */
    private void init(){
    	// this.manager = CacheManager.create(this.getConfig()); 
    	this.manager = new CacheManager(this.getConfig()); 
    	this.devCache = this.manager.getCache(DEV_MAP_CACHE);  
    	this.devtpModelCache = this.manager.getCache(DEVTP_MODEL_CACHE);  
    	this.projDBParaCache = this.manager.getCache(PROJ_DBPARA_CACHE);  
    	this.devtpExtCache = this.manager.getCache(DEVTP_EXT_CACHE);
    	this.sensorPVCache = this.manager.getCache(SENSOR_DEV_MAP_CACHE);
    	this.combineDataCache = this.manager.getCache(COMBINE_DATA_CACHE);
    	this.ffdevDataCache = this.manager.getCache(FF_DEV_CACHE);
    	this.ffaddrDataCache = this.manager.getCache(FF_ADDR_CACHE);
    	this.ffnewDataCache = this.manager.getCache(FF_NEWDATA_CACHE);
        this.photoDataCache = this.manager.getCache(PHOTO_DATA_CACHE);
    	this.resShadowCache = this.manager.getCache(RES_MAP_CACHE);
    	this.resNewIndexDataCache = this.manager.getCache(RES_INDEX_DATA_CACHE);
    	this.lowPowerAlarmFlagCache = this.manager.getCache(LOW_POWER_ALARM_FLAG_CACHE);
    	// 加载缓存
    	this.startLoadDataFromDB();
    }
    
    /**
     * 配置对象构建
     * 
     * @return Configuration
     * <cache name="iccId2GprsUseCache" 
        maxElementsInMemory="1000"   
    	eternal="false"   
    	timeToIdleSeconds="2592000"
    	timeToLiveSeconds="2592000"
		diskPersistent="false"     
        memoryStoreEvictionPolicy="LRU">		
    </cache>
     */
    private Configuration getConfig() {
    	/***
    	 *  缓存名称(必须唯一),maxElements内存最多可以存放的元素的数量 1000;
    	 *  清理机制：LRU最近最少使用 FIFO先进先出 LFU较少使用;
    	 *  元素最大闲置时间 无限时长, 元素最大生存时间 无限时长（对象永久缓存后这两项已经无意义了） ;
    	 *  元素永久缓存，超限对象对象超出时交换到磁盘.
    	 ***/
    	CacheConfiguration ccf1 = new CacheConfiguration(DEV_MAP_CACHE, 5000)
    			.timeToIdleSeconds(0)
    			.timeToLiveSeconds(0)
    			.eternal(true)
    			.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
    			.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    	
    	CacheConfiguration ccf2 = new CacheConfiguration(DEVTP_MODEL_CACHE, 500)
    			.timeToIdleSeconds(0)
    			.timeToLiveSeconds(0)
    			.eternal(true)
    			.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
    			.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    	
    	CacheConfiguration ccf3 = new CacheConfiguration(PROJ_DBPARA_CACHE, 200)
    			.timeToIdleSeconds(0)
    			.timeToLiveSeconds(0)
    			.eternal(true)
    			.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
    			.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    	CacheConfiguration ccf4 = new CacheConfiguration(DEVTP_EXT_CACHE, 200)
    			.timeToIdleSeconds(0)
    			.timeToLiveSeconds(0)
    			.eternal(true)
    			.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
    			.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);  
    	CacheConfiguration ccf5 = new CacheConfiguration(SENSOR_DEV_MAP_CACHE, 5000)
    			.timeToIdleSeconds(0)
    			.timeToLiveSeconds(0)
    			.eternal(true)
    			.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
    			.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);      	
    	CacheConfiguration ccf6 = new CacheConfiguration(COMBINE_DATA_CACHE, 1000)
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);  
    	CacheConfiguration ccf7 = new CacheConfiguration(FF_DEV_CACHE, 2000)
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);  
    	CacheConfiguration ccf8 = new CacheConfiguration(FF_ADDR_CACHE, 2000)
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    	CacheConfiguration ccf9 = new CacheConfiguration(FF_NEWDATA_CACHE, 1000) 
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    	CacheConfiguration ccf10 = new CacheConfiguration(RES_MAP_CACHE, 5000) 
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);

        CacheConfiguration ccf11 = new CacheConfiguration(PHOTO_DATA_CACHE, 1000) 
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
        
        CacheConfiguration ccf12 = new CacheConfiguration(RES_INDEX_DATA_CACHE, 2000) 
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
        
        CacheConfiguration ccf13 = new CacheConfiguration(LOW_POWER_ALARM_FLAG_CACHE, 5000) 
				.timeToIdleSeconds(0)
				.timeToLiveSeconds(0)
				.eternal(true)
				.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
				.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
				    	
        // 外层配置
        Configuration config = new Configuration();    
        config.setName("BaseCacheManager");
    	config.diskStore(new DiskStoreConfiguration().path("java.io.tmpdir")); 
    	//缓存名称(必须唯一) 
    	config.addCache(ccf1);
    	config.addCache(ccf2);
    	config.addCache(ccf3);
    	config.addCache(ccf4);
    	config.addCache(ccf5);
    	config.addCache(ccf6);
    	config.addCache(ccf7);
    	config.addCache(ccf8);
    	config.addCache(ccf9);
    	config.addCache(ccf10);
    	config.addCache(ccf11);
    	config.addCache(ccf12);
    	config.addCache(ccf13);
    	return config;
    }
    
    /**
     * 系统启动时，从数据库加载dev数据到缓存.
     */
    private void startLoadDataFromDB(){
    	logger.info("start load dev data from DB...");
    	// 多线程分别加载数据
    	Thread t1 = new Thread(new Runnable(){
			@Override
			public void run() {
				loadDevDataFromDB();
			}
    	});
    	t1.start();
    	// 多线程分别加载数据
    	Thread t2 = new Thread(new Runnable(){
			@Override
			public void run() {
				loadFFResDevDataFromDB();
			}
    	});
    	t2.start();
    	logger.info("Worker for LoadDataFromDB is started...");
    }
    
    /**
     * 加载用户权限信息，同时更新两个缓存：userInfoCache，smcommoncache
     */
	private void loadDevDataFromDB(){
		try{
			List<DevTpExtData> dtpExtDataList = this.devtpMapper.getDevTpExtDatas();
    		if (dtpExtDataList != null) {
				for (DevTpExtData dtpExt : dtpExtDataList) {
					this.devtpExtCache.put(new Element(dtpExt.getDevtpid(), dtpExt));	
				}
			}
    		logger.info("loadDevTypeExtDataFromDB ok!");
		}catch(Exception ex){
    		logger.error("loadDevTypeExtDataFromDB failed!", ex);
    	}		
    	logger.info("Begin load dev data from DB...");
    	try{
    		// 加载project的dbpara参数 ... 
    		List<ProjectDBPara> pdbps = this.projMapper.getAllProjectDBPara();
			if (pdbps != null) {
				for (ProjectDBPara p : pdbps) {
					// 解密口令...
					p.setDbpswd(SecurityUtil.AESCbcDecrypt(p.getDbpswd()));
					this.putProjDBPara4Init(p);
				}
			}
    		logger.info("loadProjectDBParaDataFromDB ok!");
    	}catch(Exception ex){
    		logger.error("loadProjectDBParaDataFromDB failed!", ex);
    	}
    	// load dev from db...
    	try{
    		DevPagePara pp = new DevPagePara();
    		pp.setBatch(5000);
    		int pageindex = 1;
    		pp.setPageIndex(pageindex);
    		boolean hasMore = true;
    		while(hasMore){
    			List<DevBase> devList = this.devMapper.queryDevs(pp);
    			if(devList == null || devList.size() == 0){
    				hasMore = false;    
    				continue;
    			}
    			pageindex++;
    			pp.setPageIndex(pageindex);
    			for(DevBase dev : devList){
    				this.putDev4Init(dev);
    			}   
    			try{
    				Thread.sleep(5);
    			}catch(Exception ignore){}
    		}
    		logger.info("loadDevDataFromDB success!");
    	}catch(Exception e){
    		logger.error("loadDevDataFromDB failed!", e);
    	}
    	// load sensor 2 deveui data from db...
    	try{
    		DevPagePara pp = new DevPagePara();
    		pp.setBatch(5000);
    		int pageindex = 1;
    		pp.setPageIndex(pageindex);
    		boolean hasMore = true;
    		while(hasMore){
    			List<SensorDevEuiPV> sensorPvList = this.devMapper.querySensorDevEuiPVs(pp);
    			if(sensorPvList == null || sensorPvList.size() == 0){
    				hasMore = false;    
    				continue;
    			}
    			pageindex++;
    			pp.setPageIndex(pageindex);
    			for(SensorDevEuiPV pv : sensorPvList){
    				this.putSensorPv4Init(pv);
    			}   
    			try{
    				Thread.sleep(5);
    			}catch(Exception ignore){}
    		}
    		logger.info("loadSensor2DeveuiDataFromDB success!");
    	}catch(Exception e){
    		logger.error("loadSensor2DeveuiDataFromDB failed!", e);
    	}
    }
	
	/**
	 * 加载消防设施逻辑资源.
	 */
	private void loadFFResDevDataFromDB(){
		try{
			// 1.查询消防用户信息传输装置.
			FFResDevBase para = new FFResDevBase();			
			boolean hasMore = true;
			int offset = 0;
			int cc = 0;
			int batch = 1000;
    		while(hasMore){
    			List<FFResDevBase> transDevList = this.ffResMapper.queryFFTransDevs(para, offset, batch);
    			if(transDevList == null || transDevList.size() == 0){
    				hasMore = false;    
    				continue;
    			}
    			cc++;
    			offset = cc * batch;
    			for(FFResDevBase ffdev : transDevList){
    				this.putFFResDevBase4Init(ffdev);
    			}   
    			if(transDevList.size() < batch){
    				hasMore = false;    
    				continue;
    			}
    			try{
    				Thread.sleep(5);
    			}catch(Exception ignore){}
    		}
    		
    		// 2.查询消防主机系统.
			para = new FFResDevBase();			
			hasMore = true;
			offset = 0;
			cc = 0;
			batch = 1000;
    		while(hasMore){
    			List<FFResDevBase> hostDevList = this.ffResMapper.queryFFHostDevs(para, offset, batch);
    			if(hostDevList == null || hostDevList.size() == 0){
    				hasMore = false;    
    				continue;
    			}
    			cc++;
    			offset = cc * batch;
    			for(FFResDevBase ffdev : hostDevList){
    				this.putFFResDevBase4Init(ffdev);
    			}   
    			if(hostDevList.size() < batch){
    				hasMore = false;    
    				continue;
    			}
    			try{
    				Thread.sleep(5);
    			}catch(Exception ignore){}
    		}
    		
    		// 3.查询消防设施部件.
			para = new FFResDevBase();			
			hasMore = true;
			offset = 0;
			cc = 0;
			batch = 1000;
    		while(hasMore){
    			List<FFResDevBase> partDevList = this.ffResMapper.queryFFHostPartDevs(para, offset, batch);
    			if(partDevList == null || partDevList.size() == 0){
    				hasMore = false;    
    				continue;
    			}
    			cc++;
    			offset = cc * batch;
    			for(FFResDevBase ffdev : partDevList){
    				this.putFFResDevBase4Init(ffdev);
    			}   
    			if(partDevList.size() < batch){
    				hasMore = false; 
    				continue;
    			}
    			try{
    				Thread.sleep(5);
    			}catch(Exception ignore){}
    		}
    		logger.info("loadFFResDevDataFromDB success!");
    	}catch(Exception e){
    		logger.error("loadFFResDevDataFromDB failed!", e);
    	}
	}
    
    /**
     * 下电退出，銷毀緩存.
     * 
     * 注意：務必系統退出或tomcat退出時調用.
     */
    public void shutdown(){
    	if(this.devCache != null){
    		this.devCache.dispose();
    		this.devCache = null;
    	}
    	if(this.devtpModelCache != null){
    		this.devtpModelCache.dispose();
    		this.devtpModelCache = null;
    	}
    	if(this.projDBParaCache != null){
    		this.projDBParaCache.dispose();
    		this.projDBParaCache = null;
    	}    	
    	if(this.devtpExtCache != null){
    		this.devtpExtCache.dispose();
    		this.devtpExtCache = null;
    	}
    	if(this.sensorPVCache != null){
    		this.sensorPVCache.dispose();
    		this.sensorPVCache = null;
    	}
    	if(this.ffdevDataCache != null){
    		this.ffdevDataCache.dispose();
    		this.ffdevDataCache = null;
    	}
    	if(this.ffaddrDataCache != null){
    		this.ffaddrDataCache.dispose();
    		this.ffaddrDataCache = null;
    	}    
    	if(this.ffnewDataCache != null){
    		this.ffnewDataCache.dispose();
    		this.ffnewDataCache = null;
    	} 
    	if(this.resShadowCache != null){
    		this.resShadowCache.dispose();
    		this.resShadowCache = null;
    	}
		if(this.photoDataCache != null){
    		this.photoDataCache.dispose();
    		this.photoDataCache = null;
    	}     		
		if(this.resNewIndexDataCache != null){
    		this.resNewIndexDataCache.dispose();
    		this.resNewIndexDataCache = null;
    	}   
		if(this.combineDataCache != null){
    		this.combineDataCache.dispose();
    		this.combineDataCache = null;
    	}       	
		if(this.lowPowerAlarmFlagCache != null){
			this.lowPowerAlarmFlagCache.dispose();
			this.lowPowerAlarmFlagCache = null;
		}
    	if(this.manager != null){
    		this.manager.shutdown();
    		this.manager = null;
    	}
    }
    
    /**
     * put projectdbpara data to cache
     * 
     * @param dev
     * 
     */
	public void putProjDBPara4Init(ProjectDBPara p) {
		if (p == null) {
			return;
		}
		String projectId = p.getProjectid();
		this.projDBParaCache.put(new Element(projectId, p));			
		logger.debug("put ProjDBPara to cache ok: "+projectId);
	}
	
	/**
     * put dev data to cache
     * 
     * @param dev
     * 
     */
	private void putDev4Init(DevBase dev) {
		if (dev == null) {
			return;
		}
		String devEui = dev.getDevEui();
		this.devCache.put(new Element(devEui, dev));			
		logger.debug("put dev to cache ok: "+devEui);
	}
	
	// init cache.
	private void putSensorPv4Init(SensorDevEuiPV pv){
		if (pv == null) {
			return;
		}
		this.sensorPVCache.put(new Element(pv.getSensorid(), pv));			
		logger.debug("put SensorDevEuiPV to cache ok: "+pv.getSensorid());
	}
	
	/**
     * put projectdbpara data to cache
     * 
     * @param dev
     * 
     */
	public void putFFResDevBase4Init(FFResDevBase d) {
		if (d == null) {
			return;
		}
		this.ffdevDataCache.put(new Element(d.getDeveui(), d));	
		this.ffaddrDataCache.put(new Element(d.buildAddrCacheKey(), d));	    	
		logger.debug("put FResDevBase to cache ok: "+d.getDeveui());
	}
	
	/**
	 * 
	 * @param devEui
	 */
	public DevBase reloadDevDirect(String devEui) {
		DevBase dev = null;
		try {
			dev = this.devMapper.queryDevByEui(devEui);
			if(dev != null){
				putDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadDev failed: deveui="+devEui+", err="+e.getMessage());
		}
		return dev;
	}

    /**
     * put dev data to cache
     * 
     * @param user
     * 
     */
	public void putDev(DevBase dev) {
		if (dev == null) {
			return;
		}
		String devEui = dev.getDevEui();
		this.devCache.acquireWriteLockOnKey(devEui);
		try {
			this.devCache.put(new Element(devEui, dev));			
			logger.debug("put dev to cache ok: "+devEui);
		} finally {
			this.devCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	public void removeDev(String devEui) {
		if (devEui == null) {
			return;
		}
		this.devCache.acquireWriteLockOnKey(devEui);
		try {
			this.devCache.remove(devEui);			
			logger.debug("remove dev from cache ok: "+devEui);
		} finally {
			this.devCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public DevBase getDev(String devEui) {
		Element cacheObj = this.devCache.get(devEui);
		if(cacheObj == null){
			logger.warn("Dev not exist in cache and try to reload it: " + devEui);
			return this.reloadDevDirect(devEui);
		}
		return (DevBase)cacheObj.getObjectValue();
	}
	
	/**
     * put DevTypeModel data to cache
     * 
     * @param dtm 
     * 
     */
	public void putDevTypeModel(DevTypeModel dtm) {
		if (dtm == null) {
			return;
		}
		String devTypeId = dtm.getDevTypeId();
		this.devtpModelCache.acquireWriteLockOnKey(devTypeId);
		try {
			this.devtpModelCache.put(new Element(devTypeId, dtm));			
			logger.debug("put devtypemodel to cache ok: "+devTypeId);
		} finally {
			this.devtpModelCache.releaseWriteLockOnKey(devTypeId);
		}
	}
	
	/**
	 * 从缓存查询devtypemodel
	 * 
	 * @param userId
	 * @return
	 */
	public DevTypeModel getDevTypeModel(String devTypeId) {
		Element cacheObj = this.devtpModelCache.get(devTypeId);
		if(cacheObj == null){
			logger.warn("There is no devtype model in cache: " + devTypeId);
			return this.reloadDevTypeModelDirect(devTypeId);
		}
		return (DevTypeModel)cacheObj.getObjectValue();
	}
	
	/**
	 * 从缓存查询DevTypeBase
	 * 
	 * @param userId
	 * @return
	 */
	public DevTypeBase getDevTypeBase(String devTypeId) {
		Element cacheObj = this.devtpModelCache.get(devTypeId);
		if(cacheObj == null){
			logger.warn("There is no devtype model in cache: " + devTypeId);
			DevTypeModel dtm = this.reloadDevTypeModelDirect(devTypeId);
			if(dtm != null){
				return dtm.getBase();
			}
			return null;
		}
		return ((DevTypeModel)cacheObj.getObjectValue()).getBase();
	}
	
	/**
	 * 加载设备类型的模型
	 * 
	 * @param devTypeId
	 */
	public DevTypeModel reloadDevTypeModelDirect(String devTypeId) {
		DevTypeModel dtm = new DevTypeModel();
		dtm.setDevTypeId(devTypeId);
		try {
			DevTypeBase dtb = this.devtpMapper.getDevtypeBase(devTypeId);
			dtm.setBase(dtb);
			dtm.setDmList(this.devtpMapper.getDevtypeDataModel(devTypeId));
			dtm.setCmList(this.devtpMapper.getDevtypeCmdModel(devTypeId));
			// 查询逻辑资源的指标模型.
			ResIndexDataModel para = new ResIndexDataModel();
			para.setTypeid(devTypeId);
			dtm.setResIndexDMList(this.resIndexModelMapper.selectByCondition(para));
			// 添加到缓存...
			putDevTypeModel(dtm);
		}catch(Exception e){
			logger.error("reloadDevTypeModelDirect failed: deveui="+devTypeId+", err="+e.getMessage());
		}
		return dtm;
	}
	
	/**
	 * ProjectDBPara; 
	 * @param devEui
	 */
	public ProjectDBPara reloadProjDBPara(String projectId) {
		ProjectDBPara p = null;
		try {
			p = this.projMapper.getProjectDBPara(projectId);
			if(p != null){
				// 解密口令...
				p.setDbpswd(SecurityUtil.AESCbcDecrypt(p.getDbpswd()));				
			} else {
				// 为了避免反复读取数据库，这里设置一个无效占位对象.
				p = new ProjectDBPara();
				p.setDbip(ProjectDBPara.INVALID_IP);
				p.setDbport(0);
				p.setProjectid(projectId);
				putProjDBPara(p);
			}
		}catch(Exception e){
			logger.error("reloadProjDBPara failed: projectId="+projectId+", err="+e.getMessage());
		}
		return p;
	}

    /**
     * put ProjectDBPara; 
     * 
     * @param user
     * 
     */
	public void putProjDBPara(ProjectDBPara p) {
		if (p == null) {
			return;
		}
		String projectId = p.getProjectid();
		this.projDBParaCache.acquireWriteLockOnKey(projectId);
		try {
			this.projDBParaCache.put(new Element(projectId, p));			
			logger.debug("put ProjDBPara to cache ok: "+projectId);
		} finally {
			this.projDBParaCache.releaseWriteLockOnKey(projectId);
		}
	}
	
	/**
     * remove ProjectDBPara; 
     * 
     * @param user
     * 
     */
	public void removeProjDBPara(String projectId) {
		if (projectId == null) {
			return;
		}
		this.projDBParaCache.acquireWriteLockOnKey(projectId);
		try {
			this.projDBParaCache.remove(projectId);		
			logger.debug("put ProjDBPara to cache ok: "+projectId);
		} finally {
			this.projDBParaCache.releaseWriteLockOnKey(projectId);
		}
	}
	
	/**
	 * 从缓存查询ProjectDBPara
	 * 
	 * @param projectId
	 * @return
	 */
	public ProjectDBPara getProjDBPara(String projectId) {
		Element cacheObj = this.projDBParaCache.get(projectId);
		if(cacheObj == null){
			logger.warn("ProjectDBPara not exist in cache and try to reload it: " + projectId);
			return this.reloadProjDBPara(projectId);
		}
		return (ProjectDBPara)cacheObj.getObjectValue();
	}
	
	/**
	 *  devtype extdata cache
     * 
     * @param devTpId
     * @return
     */
    public DevTpExtData getDevTpExtData(String devTpId){    	
    	Element cacheObj = this.devtpExtCache.get(devTpId);
		if(cacheObj == null){
			logger.warn("Devtype Extdata not exist in cache (maybe undefined): " + devTpId);
			return null;
		}
		return (DevTpExtData)cacheObj.getObjectValue();
    }
    
    /**
     * put dev ext data to cache
     * 
     * @param user
     * 
     */
	public void putDevTpExtData(DevTpExtData dtpExt) {
		if (dtpExt == null) {
			return;
		}
		String dtpid = dtpExt.getDevtpid();
		this.devtpExtCache.acquireWriteLockOnKey(dtpid);
		try {
			this.devtpExtCache.put(new Element(dtpid, dtpExt));	
			logger.debug("put dev extdata to cache ok: "+dtpid);
		} finally {
			this.devtpExtCache.releaseWriteLockOnKey(dtpid);
		}
	}  
	
	/**
     * remove dev ext data to cache
     * 
     * @param user
     * 
     */
	public void removeDevTpExtData(String dtpid) {
		if (dtpid == null) {
			return;
		}
		this.devtpExtCache.acquireWriteLockOnKey(dtpid);
		try {
			this.devtpExtCache.remove(dtpid);		
			logger.debug("remove dev extdata from cache ok: "+dtpid);
		} finally {
			this.devtpExtCache.releaseWriteLockOnKey(dtpid);
		}
	}  
	
	/**
	 * 重新加载...
	 * @param sensorid
	 */
	public SensorDevEuiPV reloadSensorDevEuiPV(String sensorId) {
		SensorDevEuiPV pv = null;
		try {
			pv = this.devMapper.querySensorDevEuiPV(sensorId);
			if(pv != null){
				this.putSensorDevEuiPV(pv);
			}
		}catch(Exception e){
			logger.error("reloadSensorDevEuiPV failed: sensorId="+sensorId+", err="+e.getMessage());
		}
		return pv;
	}

    /**
     * put SensorDevEuiPV data to cache
     * 
     * @param user
     * 
     */
	public void putSensorDevEuiPV(SensorDevEuiPV pv) {
		if (pv == null) {
			return;
		}
		String sensorId = pv.getSensorid();
		this.sensorPVCache.acquireWriteLockOnKey(sensorId);
		try {
			this.sensorPVCache.put(new Element(sensorId, pv));			
			logger.debug("put SensorDevEuiPV to cache ok: "+sensorId);
		} finally {
			this.sensorPVCache.releaseWriteLockOnKey(sensorId);
		}
	}
	
	public void removeSensorDevEuiPV(String sensorId) {
		if (sensorId == null) {
			return;
		}
		this.sensorPVCache.acquireWriteLockOnKey(sensorId);
		try {
			this.sensorPVCache.remove(sensorId);			
			logger.debug("remove SensorDevEuiPV from cache ok: "+sensorId);
		} finally {
			this.sensorPVCache.releaseWriteLockOnKey(sensorId);
		}
	}
	
	/**
	 * 从缓存查询SensorDevEuiPV
	 * 
	 * @param sensorId
	 * @return SensorDevEuiPV
	 */
	public SensorDevEuiPV getSensorDevEuiPV(String sensorId){
		Element cacheObj = this.sensorPVCache.get(sensorId);
		if(cacheObj == null){
			logger.warn("SensorDevEuiPV not exist in cache and try to reload it: " + sensorId);
			return this.reloadSensorDevEuiPV(sensorId);
		}
		return (SensorDevEuiPV)cacheObj.getObjectValue();
	}
	
	 /**
     * put DevMeteData data to cache
     * 
     * @param data
     * 
     */
	public void putCombineData(DevMeteData data) {
		if (data == null) {
			return;
		}
		String devEui = data.getDeveui();
		this.combineDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.combineDataCache.put(new Element(devEui, data));			
			logger.debug("put putCombineData to cache ok: "+devEui);
		} finally {
			this.combineDataCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	public void removeCombineData(String devEui) {
		if (devEui == null) {
			return;
		}
		this.combineDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.combineDataCache.remove(devEui);			
			logger.debug("remove CombineData from cache ok: "+devEui);
		} finally {
			this.combineDataCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	/**
	 * 从缓存查询CombineData
	 * 
	 * @param devEui
	 * @return CombineData
	 */
	public DevMeteData getCombineData(String devEui){
		Element cacheObj = this.combineDataCache.get(devEui);
		if(cacheObj != null){
			return (DevMeteData)cacheObj.getObjectValue();
		}
		return null;
	}	
	
	/**
     * put Res index DevMeteData data to cache
     * 
     * @param data
     * 
     */
	public void putResNewIndexData(DevMeteData data) {
		if (data == null) {
			return;
		}
		String devEui = data.getDeveui();
		this.resNewIndexDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.resNewIndexDataCache.put(new Element(devEui, data));			
			logger.debug("put resNewIndexData to cache ok: "+devEui);
		} finally {
			this.resNewIndexDataCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	public void removeResNewIndexData(String devEui) {
		if (devEui == null) {
			return;
		}
		this.resNewIndexDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.resNewIndexDataCache.remove(devEui);			
			logger.debug("remove resNewIndexData from cache ok: "+devEui);
		} finally {
			this.resNewIndexDataCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	/**
	 * 从缓存查询resNewIndexData
	 * 
	 * @param devEui
	 * @return CombineData
	 */
	public DevMeteData getResNewIndexData(String devEui){
		Element cacheObj = this.resNewIndexDataCache.get(devEui);
		if(cacheObj != null){
			return (DevMeteData)cacheObj.getObjectValue();
		}
		return null;
	}	

    /**
     * put ffres data to cache
     * 
     * @param user
     * 
     */
	public void putFFResDev(FFResDevBase dev) {
		if (dev == null) {
			return;
		}
		String devEui = dev.getDeveui();
		this.ffdevDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.ffdevDataCache.put(new Element(devEui, dev));			
			logger.debug("put dev to cache ok: "+devEui);
		} finally {
			this.ffdevDataCache.releaseWriteLockOnKey(devEui);
		}
		String addrCacheKey = dev.buildAddrCacheKey();
		this.ffaddrDataCache.acquireWriteLockOnKey(addrCacheKey);
		try {
			this.ffaddrDataCache.put(new Element(addrCacheKey, dev));			
			logger.debug("[2]put dev to cache ok: "+addrCacheKey);
		} finally {
			this.ffaddrDataCache.releaseWriteLockOnKey(addrCacheKey);
		}
	}
	
	public void removeFFResDev(String devEui) {
		if (devEui == null) {
			return;
		}
		this.ffdevDataCache.acquireWriteLockOnKey(devEui);
		try {
			this.ffdevDataCache.remove(devEui);		
			logger.debug("remove dev from cache ok: "+devEui);
		} finally {
			this.ffdevDataCache.releaseWriteLockOnKey(devEui);
		}
	}
	
	public void removeFFResDevByKey(String addrKey) {
		if (addrKey == null) {
			return;
		}
		this.ffaddrDataCache.acquireWriteLockOnKey(addrKey);
		try {
			this.ffaddrDataCache.remove(addrKey);		
			logger.debug("remove dev from cache ok: "+addrKey);
		} finally {
			this.ffaddrDataCache.releaseWriteLockOnKey(addrKey);
		}
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFTransDevByEui(String devEui) {
		Element cacheObj = this.ffdevDataCache.get(devEui);
		if(cacheObj == null){
			logger.warn("Dev not exist in cache and try to reload it: " + devEui);
			return this.reloadFFTransDevByEui(devEui);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFTransDevByEui(String devEui) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFTransDevByEui(devEui);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFTransDevByEui failed: deveui="+devEui+", err="+e.getMessage());
		}
		return dev;
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFTransDevByAddr(String transdevAddr) {
		FFResDevBase d = new FFResDevBase();
		d.setTransdevaddr(transdevAddr);
		String addrCacheKey = d.buildAddrCacheKey();
		Element cacheObj = this.ffaddrDataCache.get(addrCacheKey);
		if(cacheObj == null){
			logger.warn("FFTransDev not exist in cache and try to reload it: " + transdevAddr);
			return this.reloadFFTransDevByAddr(transdevAddr);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFTransDevByAddr(String transdevAddr) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFTransDevByAddr(transdevAddr);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFTransDevByAddr failed: deveui="+transdevAddr+", err="+e.getMessage());
		}
		return dev;
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFHostDevByEui(String devEui) {
		Element cacheObj = this.ffdevDataCache.get(devEui);
		if(cacheObj == null){
			logger.warn("Dev not exist in cache and try to reload it: " + devEui);
			return this.reloadFFHostDevByEui(devEui);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFHostDevByEui(String devEui) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFHostDevByEui(devEui);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFHostDevByEui failed: deveui="+devEui+", err="+e.getMessage());
		}
		return dev;
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFHostDevByAddr(String transdevAddr, int sysAddr) {
		FFResDevBase d = new FFResDevBase();
		d.setTransdevaddr(transdevAddr);
		d.setSysaddr(sysAddr);
		String addrCacheKey = d.buildAddrCacheKey();
		Element cacheObj = this.ffaddrDataCache.get(addrCacheKey);
		if(cacheObj == null){
			logger.warn("FFHostDev not exist in cache and try to reload it: " + addrCacheKey);
			return this.reloadFFHostDevByAddr(transdevAddr, sysAddr);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFHostDevByAddr(String transdevAddr, int sysAddr) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFHostDevByAddr(transdevAddr, sysAddr);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFHostDevByAddr failed: transdevaddr={}, sysaddr={}, err=[}", transdevAddr, sysAddr, e.getMessage());
		}
		return dev;
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFPartDevByEui(String devEui) {
		Element cacheObj = this.ffdevDataCache.get(devEui);
		if(cacheObj == null){
			logger.warn("PartDev not exist in cache and try to reload it: " + devEui);
			return this.reloadFFPartDevByEui(devEui);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFPartDevByEui(String devEui) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFHostPartDevByEui(devEui);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFPartDevByEui failed: deveui="+devEui+", err="+e.getMessage());
		}
		return dev;
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public FFResDevBase getFFPartDevByAddr(String transdevAddr, int sysAddr, String partAddr) {
		FFResDevBase d = new FFResDevBase();
		d.setTransdevaddr(transdevAddr);
		d.setSysaddr(sysAddr);
		d.setPartaddr(partAddr);
		String addrCacheKey = d.buildAddrCacheKey();
		Element cacheObj = this.ffaddrDataCache.get(addrCacheKey);
		if(cacheObj == null){
			logger.warn("FFPartDev not exist in cache and try to reload it: " + addrCacheKey);
			return this.reloadFFPartDevByAddr(transdevAddr, sysAddr, partAddr);
		}
		return (FFResDevBase)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param devEui
	 */
	private FFResDevBase reloadFFPartDevByAddr(String transdevAddr, int sysAddr, String partAddr) {
		FFResDevBase dev = null;
		try {
			dev = this.ffResMapper.queryFFHostPartDevByAddr(transdevAddr, sysAddr, partAddr);
			if(dev != null){
				putFFResDev(dev);
			}
		}catch(Exception e){
			logger.error("reloadFFPartDevByAddr failed: transdevaddr={}, sysaddr={}, partaddr={}, err=[}", transdevAddr, sysAddr, partAddr, e.getMessage());
		}
		return dev;
	}
	
	/**
     * put FF DEV latest data to cache
     * 
     * @param user
     * 
     */
	public void putFFLatestData(String ffDevEui, String ffJsonData) {
		if (ffJsonData == null) {
			return;
		}
		this.ffnewDataCache.acquireWriteLockOnKey(ffDevEui);
		try {
			this.ffnewDataCache.put(new Element(ffDevEui, ffJsonData));			
			logger.debug("putFFLatestData to cache ok: "+ffJsonData);
		} finally {
			this.ffnewDataCache.releaseWriteLockOnKey(ffDevEui);
		}
	}
	
	/**
     * get FF DEV latest data to cache
     * 
     * @param user
     * 
     */
	public String getFFLatestData(String ffDevEui) {		
		Element cacheObj = this.ffnewDataCache.get(ffDevEui);
		if(cacheObj == null){
			return null;
		}
		return (String)cacheObj.getObjectValue();
	}
	
	/**
	 * 
	 * @param resId
	 */
	public ResourceShadow reloadResDirect(String resId) {
		ResourceShadow dev = null;
		try {
			dev = this.resShadowMapper.queryResShadow(resId);
			if(dev != null){
				putRes(dev);
			}
		}catch(Exception e){
			logger.error("reloadRes failed: deveui="+resId+", err="+e.getMessage());
		}
		return dev;
	}
	
    /**
     * put RES data to cache
     * 
     * @param RES
     * 
     */
	public void putRes(ResourceShadow res) {
		if (res == null) {
			return;
		}
		String resId = res.getResid();
		this.resShadowCache.acquireWriteLockOnKey(resId);
		try {
			this.resShadowCache.put(new Element(resId, res));			
			logger.debug("put res to cache ok: "+resId);
		} finally {
			this.resShadowCache.releaseWriteLockOnKey(resId);
		}
	}
	
	public void removeRes(String resId) {
		if (resId == null || resId.equals("")) {
			return;
		}
		this.resShadowCache.acquireWriteLockOnKey(resId);
		try {
			this.resShadowCache.remove(resId);			
			logger.debug("remove RES from cache ok: "+resId);
		} finally {
			this.resShadowCache.releaseWriteLockOnKey(resId);
		}
	}
	
	/**
	 * 从缓存查询dev
	 * 
	 * @param userId
	 * @return
	 */
	public ResourceShadow getRes(String resId) {
		Element cacheObj = this.resShadowCache.get(resId);
		if(cacheObj == null){
			logger.warn("Res not exist in cache and try to reload it: " + resId);
			return this.reloadResDirect(resId);
		}
		return (ResourceShadow)cacheObj.getObjectValue();
	}
	
	/**
	 * 告警码模型查询.
	 * 
	 */
	public AlarmCode getAlarmCode(String devtype, String alarmCode) {
		AlarmCode ac = this.alarmCodeMap.get(devtype+"."+alarmCode);
		if(ac == null){
			ac = this.alarmCodeMapper.getAlarmCode(devtype, alarmCode);
			if(ac != null){
				this.alarmCodeMap.put(devtype+"."+alarmCode, ac);
			}
		}
		return ac;
	}
	
	public void putAlarmCode(AlarmCode ac) {
		if(ac == null){
			return;
		}
		this.alarmCodeMap.put(ac.getDevtype()+"."+ac.getAlarmcode(), ac);
	}
	
	public void removeAlarmCode(String devtype, String alarmCode) {
		this.alarmCodeMap.remove(devtype+"."+alarmCode);
	}
	
	
	
	public void putLowPowerAlarmFlag(String deveui, Integer flag) {
		if (deveui == null) {
			return;
		}	
		this.lowPowerAlarmFlagCache.acquireWriteLockOnKey(deveui);
		try {
			this.lowPowerAlarmFlagCache.put(new Element(deveui, flag));			
			logger.debug("put low power alarm flag to cache ok: " + deveui);
		} finally {
			this.lowPowerAlarmFlagCache.releaseWriteLockOnKey(deveui);
		}
	}

	
	public void removeLowPowerAlarmFlag(String deveui) {
		if (deveui == null || deveui.equals("")) {
			return;
		}
		this.lowPowerAlarmFlagCache.acquireWriteLockOnKey(deveui);
		try {
			this.lowPowerAlarmFlagCache.remove(deveui);			
			logger.debug("remove low power alarm flag to cache ok: " + deveui);
		} finally {
			this.lowPowerAlarmFlagCache.releaseWriteLockOnKey(deveui);
		}
	}
	
	
	public Integer getLowPowerAlarmFlag(String deveui) {
		Element cacheObj = this.lowPowerAlarmFlagCache.get(deveui);
		if(cacheObj == null){			
			return null;
		}
		return (Integer)cacheObj.getObjectValue();
	}
	
}
